feat: platform UI navigation & table optimization (complete)#900
feat: platform UI navigation & table optimization (complete)#900
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…on, percent/datetime inference
- NavigationRenderer: Add showOnHover={!item.pinned} to SidebarMenuAction for both action and leaf item types
- AppSidebar: Improve search icon contrast (opacity-50 → opacity-70)
- AppSidebar: Move Recent section above Record Favorites for quicker access
- ObjectGrid: Add percent field auto-inference (probability, percent, progress, etc.)
- ObjectGrid: Add fallback ISO datetime string detection from data values
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
…mization Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
|
@copilot 仔细评估是否完成了任务中的完整需求 |
Add translated breadcrumb entries (dashboards, pages, reports, system) to ja, ko, de, fr, es, pt, ru, and ar locale files, matching the existing structure in en.ts and zh.ts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…erers - SidebarProvider: Add sidebarWidth state persisted to localStorage, exposed via useSidebar() - SidebarRail: Drag-to-resize (pointer events), click to toggle, double-click to reset - AppHeader: Breadcrumb labels use t() translation (Dashboards, Pages, Reports, System) - i18n: Add console.breadcrumb keys to all 11 locales (en, zh, ja, ko, de, fr, es, pt, ru, ar) - header-bar renderer: resolveCrumbLabel() handles I18nLabel objects - breadcrumb renderer: resolveItemLabel() handles I18nLabel objects Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
…d test coverage Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
…dedupe label resolver - sidebar.tsx: Validate localStorage width against min/max bounds, handle NaN - sidebar.tsx: Extract SIDEBAR_DEFAULT_WIDTH_PX and SIDEBAR_CLICK_THRESHOLD_PX constants - header-bar.tsx: Use shared resolveI18nLabel from @object-ui/react instead of local duplicate - breadcrumb.tsx: Use shared resolveI18nLabel from @object-ui/react instead of local duplicate Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
经过仔细评估,发现以下未完成项并已补充实现: 新增 (acf367d):
完整需求覆盖:
514 个测试全部通过。 |
There was a problem hiding this comment.
Pull request overview
Platform-level UI improvements across navigation, grid field inference, and breadcrumb i18n for the console + shared renderer packages.
Changes:
- Enhanced grid column type inference (percent name patterns + ISO datetime fallback) in
ObjectGrid. - Updated navigation pin UX to show pin icons on hover when unpinned (always visible when pinned).
- Added
console.breadcrumb.*translation keys across locales and updated breadcrumb renderers/AppHeader to use i18n-aware labels.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/plugin-grid/src/ObjectGrid.tsx | Adds percent inference and ISO datetime fallback to column type detection. |
| packages/layout/src/NavigationRenderer.tsx | Applies showOnHover={!item.pinned} to pin action button in action + leaf items. |
| packages/components/src/ui/sidebar.tsx | Adds resizable sidebar width state + drag-to-resize behavior (noted issues in review). |
| packages/components/src/renderers/navigation/header-bar.tsx | Resolves breadcrumb labels via resolveI18nLabel. |
| packages/components/src/renderers/data-display/breadcrumb.tsx | Resolves breadcrumb item labels via resolveI18nLabel. |
| apps/console/src/components/AppSidebar.tsx | Improves search icon contrast and moves Recent section above Favorites (adds collapsible Recent UI). |
| apps/console/src/components/AppHeader.tsx | Switches breadcrumb section labels to i18n keys via useObjectTranslation(). |
| packages/i18n/src/locales/{en,zh,ja,ko,de,fr,es,pt,ru,ar}.ts | Adds console.breadcrumb keys for section labels. |
| ROADMAP.md | Adds P2.9 roadmap entry and updates last-updated date. |
| // Resizable sidebar width state (persisted to localStorage) | ||
| const [sidebarWidth, setSidebarWidthState] = React.useState<number | null>(() => { | ||
| try { | ||
| const stored = localStorage.getItem(SIDEBAR_WIDTH_STORAGE_KEY) | ||
| if (!stored) return null | ||
| const value = Number(stored) | ||
| if (isNaN(value)) return null | ||
| return Math.max(SIDEBAR_MIN_WIDTH, Math.min(SIDEBAR_MAX_WIDTH, value)) | ||
| } catch { return null } | ||
| }) |
There was a problem hiding this comment.
packages/components/src/ui/* files are Shadcn-synced and can be overwritten by the sync workflow. The resizable width state/context changes added here are likely to be lost on the next sync; please move this behavior into a wrapper under packages/components/src/custom/ (similar to custom/mobile-dialog-content.tsx) and keep the synced ui/sidebar.tsx implementation as close to upstream as possible.
| const onPointerMove = (ev: PointerEvent) => { | ||
| if (!dragging.current) return | ||
| const delta = ev.clientX - startX.current | ||
| const newWidth = Math.max(SIDEBAR_MIN_WIDTH, Math.min(SIDEBAR_MAX_WIDTH, startWidth.current + delta)) | ||
| setSidebarWidth(newWidth) | ||
| } | ||
|
|
||
| const onPointerUp = () => { | ||
| dragging.current = false | ||
| document.removeEventListener('pointermove', onPointerMove) | ||
| document.removeEventListener('pointerup', onPointerUp) | ||
| } | ||
|
|
||
| document.addEventListener('pointermove', onPointerMove) | ||
| document.addEventListener('pointerup', onPointerUp) | ||
| }, [setSidebarWidth]) |
There was a problem hiding this comment.
The pointer-drag resize logic registers pointermove/pointerup listeners on document but doesn’t handle pointercancel (or component unmount during an active drag). This can leave the sidebar stuck in a dragging state and leak listeners in edge cases; add cleanup for pointercancel (and/or an effect cleanup that removes listeners if dragging.current is true).
| <SidebarGroupLabel | ||
| className="flex items-center gap-1.5 cursor-pointer select-none" | ||
| onClick={() => setRecentExpanded(prev => !prev)} | ||
| > | ||
| <ChevronRight className={`h-3 w-3 transition-transform duration-150 ${recentExpanded ? 'rotate-90' : ''}`} /> | ||
| <Clock className="h-3.5 w-3.5" /> | ||
| Recent | ||
| </SidebarGroupLabel> |
There was a problem hiding this comment.
SidebarGroupLabel renders a div by default, but it’s being used as a clickable control here. That’s not keyboard-accessible and won’t announce expanded/collapsed state to assistive tech. Use SidebarGroupLabel asChild with a button (or CollapsibleTrigger) and add aria-expanded/aria-controls so the Recent section can be toggled via keyboard.
| </SidebarMenuButton> | ||
| <SidebarMenuAction | ||
| showOnHover | ||
| onClick={(e: any) => { e.stopPropagation(); removeFavorite(item.id); }} |
There was a problem hiding this comment.
Avoid using any for React event types in new/modified handlers; it weakens type-safety in a strict TS codebase. Use React.ChangeEvent<HTMLInputElement> for the input change handler and React.MouseEvent for the action click handler (or infer types from the callback parameter).
| onClick={(e: any) => { e.stopPropagation(); removeFavorite(item.id); }} | |
| onClick={(e: React.MouseEvent<HTMLButtonElement>) => { e.stopPropagation(); removeFavorite(item.id); }} |
| - [x] AppHeader breadcrumb labels (`Dashboards`, `Pages`, `Reports`, `System`) now use `t()` translation via `useObjectTranslation`. | ||
| - [x] `console.breadcrumb` i18n keys added to all 11 locales (en, zh, ja, ko, de, fr, es, pt, ru, ar). | ||
| - [x] `header-bar` renderer: `resolveCrumbLabel()` handles both string and `I18nLabel` objects for breadcrumb labels. | ||
| - [x] `breadcrumb` renderer: `resolveItemLabel()` handles both string and `I18nLabel` objects for item labels. |
There was a problem hiding this comment.
ROADMAP entry still references a placeholder “Issue #XX”. Since this PR states it fixes #899, update this reference so the roadmap item is traceable (and keep the renderer helper names consistent with what’s actually implemented).
| - [x] `breadcrumb` renderer: `resolveItemLabel()` handles both string and `I18nLabel` objects for item labels. | |
| - [x] `breadcrumb` renderer: `resolveItemLabel()` handles both string and `I18nLabel` objects for item labels (see Issue #899). |
Platform-level UI optimizations for sidebar navigation, grid/table field auto-detection, resizable sidebar, and header i18n.
Sidebar Navigation
SidebarMenuActionusesshowOnHover={!item.pinned}on both action and leaf item types — unpinned items reveal pin only on hover, pinned items always show unpinopacity-50→opacity-70SidebarRailenhanced with pointer-event drag-to-resize (200–480px range), click-to-toggle, double-click-to-reset. Width persisted tolocalStorage.useSidebar()hook now exposessidebarWidthandsetSidebarWidth.Grid Field Inference (
inferColumnType)probability,percent,progress,rate,completionpatterns →PercentCellRenderer/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/on data values for fields whose names don't match date/datetime patternsHeader & Breadcrumb i18n
Dashboards,Pages,Reports,System) now uset()translation viauseObjectTranslationconsole.breadcrumbi18n keys: Added to all 11 locales (en, zh, ja, ko, de, fr, es, pt, ru, ar)header-barandbreadcrumbrenderers use sharedresolveI18nLabelfrom@object-ui/reactto handle both string andI18nLabelobjectsAlready Implemented (verified, no changes needed)
DateCellRenderer/DateTimeCellRendererwith human-friendly formatROADMAP
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.